const defaults = require('lodash/defaults')
//默认字段&自定义字段
const defaultOptions = {
  typeName: 'type',//我称他为纽扣字段
  pushEvent: 'push',//订阅
  pullEvent: 'pull'//发布
}


module.exports = class PP {
  constructor (io, options) {
    this.options = defaults(options, defaultOptions)
    this.maps = {}//储存订阅信息。纽扣字段:[...fn]
    this.defaultMap = []//参考switch的default
    this.io = io
    this.socket = null
    this.ctx = {}
    this.eventType = null
    this.errorProcessor = null

    this.init()
  }
  //收集
  add(name, ...fn) {
    const maps = this.maps
    if (!maps[name]) maps[name] = []
    fn.forEach(f => typeof f === 'function' && maps[name].push(f))
    return this
  }
  //收集default
  default (...fn) {
    fn.forEach(f => typeof f === 'function' && this.defaultMap.push(f))
    return this
  }
  //主动触发
  type (type, ...args) {
    this.execute(type, this.socket, ...args)
    return this
  }
  //封装了socket的其他api
  _types(event, data, id) {
    const {io, socket, options, eventType} = this
    const { pullEvent, typeName} = options
    data = { [typeName]: eventType,  data }//用[表示]
    switch (event) {
      case 'oneself':
        socket.emit(pullEvent, data)
        break;
      case 'everybody':
        io.emit(pullEvent, data)
        break;
      case 'without':
        socket.broadcast.emit(pullEvent, data)
        break;
      case 'one':
        io.to(id).emit(pullEvent, data)
        break;
      case 'room':
        socket.broadcast.to(id).emit(pullEvent, data)
        break;
    }
  }

  error (fn) {
    this.errorProcessor = fn
    return this
  }

  oneself (...args) {
    this._types('oneself', ...args)
    return this
  }

  everybody (...args) {
    this._types('everybody', ...args)
    return this
  }


  without (...args) {
    this._types('without', ...args)
    return this
  }

  one (...args) {
    this._types('one', ...args)
    return this
  }

  room (...args) {
    this._types('room', ...args)
    return this
  }
  //
  connection (...args) {
    this.add('connection', ...args)
    return this
  }
  //
  disconnect (...args) {
    this.add('disconnect', ...args)
    return this
  }



  //if：匹配到订阅字段
  //else：纽扣字段不包含在'connection', 'disconnect'。则走default
  execute (type, socket, ...args) {
    this.socket = socket
    this.eventType = type
    const {maps , defaultMap} = this
    if (type in maps) {
      Array.isArray(maps[type]) && maps[type].forEach(f =>  f.apply(this, args))
    } else if (!['connection', 'disconnect'].includes(type)) {
      defaultMap.forEach(f => f.apply(this, args))
    }
  }


  init () {
    const {io, options, errorProcessor} = this
    const {pushEvent, typeName} = options
    try {
      io.on('connection', socket => {
        this.execute('connection', socket)
        socket.on(pushEvent, (msg, fn) => {
          console.log(msg, fn)
          const type = msg[typeName]
          const data = msg.data
          this.execute(type, socket, data, fn)
        })

        socket.on('disconnect', () => {
          this.execute('disconnect', socket)
        })
      })
    } catch (e) {
      if (typeof errorProcessor === 'function') errorProcessor(e)
    }
  }
}